
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>


#include <page_manager.h>
#include <disp_manager.h>
#include <input_manager.h>
#include <font_manager.h>
#include <ui.h>
#include <config.h>

#define X_GAP 5
#define Y_GAP 5


static Button g_tButtons[ITEM_MAX_NUM];
static int g_iButtonCnt;
static pDispBuff ptDispBuff;

static int MainPage_OnPressed(struct Button *ptButton, pDispBuff ptDispBuff, pInputEvent ptInputEvent)
{
	unsigned int dwColor = BUTTON_DEFAULT_COLOR;
	char name[100];
	char status[100];
	char *strButton;
	char *command_status[3] = {"err", "ok", "persent"};
	int command_status_index = 0;
	char command[1000];
	PItemCfg ptItemCfg;
	strButton = ptButton->name;
	if(strButton == NULL)
		return -1;
	/* 1.对于触摸屏事件 */
	if(ptInputEvent->iType == INPUT_TYPE_TOUCH)
	{
		/* 1.1分辨能否被点击 */
		if(GetItemCfgByName(ptButton->name)->bCanBeTouched == 0)
		{
			return -1;
		}
		/* 1.2修改颜色 */
		ptButton->status = !ptButton->status;
		if(ptButton->status)
		{
			dwColor = BUTTON_PRESSED_COLOR;
			command_status_index = 1;
		}
	}/* 2.对于网络事件 */
	else if(ptInputEvent->iType == INPUT_TYPE_NET)
	{
		/* 根据传入的字符串修改颜色 ： wifi ok, wifi error, burn 70% */
		sscanf(ptInputEvent->str, "%s %s", name, status);
		/* 状态ok */
		if(strcmp(status, "ok") == 0)
		{	
			command_status_index = 1;
			dwColor = BUTTON_PRESSED_COLOR;
		}/* 状态err */
		else if(strcmp(status, "err") == 0)
		{
			command_status_index = 0;
			dwColor = BUTTON_DEFAULT_COLOR;
		}/* 正在测试 */
		else if(status[0] >= '0' && status[0] <= '9')
		{
			command_status_index = 2;
			dwColor = BUTTON_PERCENT_COLOR;
			strButton = status;
		}/* 传入了错误的值 */
		else
		{
			return -1;
		}
	}
	else
	{
		return -1;
	}

	
	/* 绘制底色 */
	DrawRegion(&ptButton->tRegion, dwColor);

	/* 居中写文字 */
	DrawTextInReginCentral(strButton, &ptButton->tRegion, BUTTON_TEXT_COLOR);
	
	/* flush to lcd/web */
	FlushDisplayRegion(&ptButton->tRegion, ptDispBuff);

	/* 执行command */
	ptItemCfg = GetItemCfgByName(ptButton->name);
	if(ptItemCfg->command[0] != '\0')
	{
		sprintf(command, "%s %s", ptItemCfg->command, command_status[command_status_index]);
		system(command);
	}
	
	return 0;
}

static int GetFontSizeForAllButton(void)
{
	int i;
	int len, max_len = 0;
	int max_index = 0;
	float k, kx, ky;
	RegionCartesian tRegionCar;
	/* 1.找出name最长的Button */
	for(i = 0; i < g_iButtonCnt; i++)
	{
		len = strlen(g_tButtons[i].name);
		if(len > max_len)
		{
			max_len = len;
			max_index = i;
		}
	}
	/* 2.以FontSize = 100, 计算出外框 */
	SetFontSize(100);
	GetStringRegionCar(g_tButtons[max_index].name, &tRegionCar);
	
	/* 3.把文字的外框缩放为Button的外框 */
	kx = (float)g_tButtons[max_index].tRegion.iWidth / tRegionCar.iWidth;
	ky = (float)g_tButtons[max_index].tRegion.iHeight / tRegionCar.iHeight;
	
	k = kx < ky ? kx : ky;
	/* 4.反算出font size，只取0.8，避免过于接边界 */
	return k * 100 * 0.8;
}



static void GenerateButtons(void)
{
	int width, height;	//每个按钮的宽高，height=width * 0.618 
	int n_per_line;		//每一行有多少个按钮
	int row, rows;			//有多少行
	int col;
	int n;				//总共多少个按钮
		
	int xres, yres;		//分辨率
	int start_x, start_y;	//第一个按钮的起始位置
	int pre_start_x, pre_start_y;
	PButton ptButton;
	int i = 0;
	int iFontSize;
	/* 算出单个按钮的width/height */
	g_iButtonCnt = n = GetItemCfgCount();
	ptDispBuff = GetDisplayBuffer();
	xres = ptDispBuff->iXres;
	yres = ptDispBuff->iYres;
	width = sqrt(1.0 / 0.618 * xres  * yres / n);
	//width = width * 0.86;
	n_per_line = xres / width + 1;
	width = xres / n_per_line;	//计算时多一个按钮，让实际按钮小一点，避免越界
	height = 0.618 * width;
	rows 	= n / n_per_line;	//可能有余数被取整
	if(rows * n_per_line < n)	//如果不能整除就加一，因为有一个被取整丢失了
	{
		rows++;
	}
//	if(height * rows > yres)
//	{
//		height = yres / (rows + 2);
//	}
	/* 居中显示:计算每一个按钮的region */
	start_x = (xres - width * n_per_line ) / 2;
	
	
	start_y = (yres - rows * height) / 2;
	/* 计算每个按钮的region */
	for(row = 0; (row < rows) && (i < n); row++)
	{
		pre_start_y = start_y + row * height;
		pre_start_x = start_x - width;
		for(col = 0; (col < n_per_line) && (i < n); col++)
		{
			ptButton = &g_tButtons[i];
			ptButton->tRegion.iLeftUpX 	= pre_start_x + width;
			ptButton->tRegion.iLeftUpY 	= pre_start_y;
			ptButton->tRegion.iWidth   	= width - X_GAP;
			ptButton->tRegion.iHeight   = height - Y_GAP;
			pre_start_x = ptButton->tRegion.iLeftUpX;
			/* InitButton */
			InitButton(ptButton, GetItemCfgByIndex(i)->name, NULL,	NULL, MainPage_OnPressed);
			i++;
		} 
	}
	iFontSize = GetFontSizeForAllButton();
	
	/* OnDraw */
	for(i = 0; i < n; i++)
	{
		g_tButtons[i].iFontsize = iFontSize;
		g_tButtons[i].OnDraw(&g_tButtons[i], ptDispBuff);
	}
	return;
}

static int isTouchPointRegion(int iX, int iY, PRegion ptRegion)
{
	if(iX < ptRegion->iLeftUpX || iX >= ptRegion->iLeftUpX + ptRegion->iWidth)
	{
		return 0;
	}
	if(iY < ptRegion->iLeftUpY || iY >= ptRegion->iLeftUpY + ptRegion->iHeight)
	{
		return 0;
	}
	return 1;
}

static PButton GetButtonByName(char *name)
{
	int i;
	for(i = 0; i < g_iButtonCnt; i++)
	{
		if(strcmp(name, g_tButtons[i].name) == 0)
			return &g_tButtons[i];
	}
	return NULL;
}


static PButton GetButtonByInputEvent(pInputEvent ptInputEvent)
{
	int i;
	char name[100];
	if(ptInputEvent->iType == INPUT_TYPE_TOUCH)
	{
		for(i = 0; i < g_iButtonCnt; i++)
		{
			if(isTouchPointRegion(ptInputEvent->iX, ptInputEvent->iY, &g_tButtons[i].tRegion))
				return &g_tButtons[i];
		}
	}
	else if(ptInputEvent->iType == INPUT_TYPE_NET)
	{
		sscanf(ptInputEvent->str, "%s", name);
		return GetButtonByName(name);
	}

	return NULL;
}



static void MainPageRun(void *pParams)
{

	//	printf("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	int error;
	InputEvent tInputEvent;
	PButton ptButton;
	/* 读取配置文件 */
	error = ParseConfig();
	if(error)
	{
		return;
	}
	/* 根据配置文件生成按钮，界面 */
	GenerateButtons();
	while(1)
	{
		/* 读取输入事件 */
		error = GetInputEvent(&tInputEvent);
		if(error)
			continue;
		//printf("GetInputEvent %d\n", tInputEvent.iType);
		/* 根据输入事件找到按钮 */
		ptButton = GetButtonByInputEvent(&tInputEvent);
		if(ptButton == NULL)
			continue;
		//printf("GetButtonByInputEvent %d\n", tInputEvent.iType);
		/* 调用按钮的OnPressed函数 */
		ptButton->OnPressed(ptButton, ptDispBuff, &tInputEvent);
	}
}


static PageAction g_tMainPage = {
	.name = "main",
	.Run = MainPageRun,
};

void MainPageRegister(void)
{
	PageRegister(&g_tMainPage);
}

